package util;

import com.alibaba.fastjson.JSON;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.CSVRecord;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.util.CollectionUtils;

import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * \* User: MeiZhongHao
 * \* Date: 2018-12-14
 * \* Time: 10:26
 * \* Description:
 * \
 */
public class CsvUtil {

    private static final Logger logger = LogManager.getLogger(CsvUtil.class);

    //CSV文件分隔符
    private final static String NEW_LINE_SEPARATOR = "\n";
    //初始化csvformat
    private final static CSVFormat formator = CSVFormat.DEFAULT.withRecordSeparator(NEW_LINE_SEPARATOR);

    /**
     * 写入csv文件
     *
     * @param headers  列头
     * @param data     数据内容
     * @param filePath 创建的csv文件路径
     * @throws IOException
     **/
    public static void writeCsv(String[] headers, List<String[]> data, String filePath) throws IOException {
        //创建FileWriter对象
        FileWriter fileWriter = new FileWriter(filePath);
        //创建CSVPrinter对象
        CSVPrinter printer = new CSVPrinter(fileWriter, formator);
        //写入列头数据
        printer.printRecord(headers);
        if (null != data) {
            //循环写入数据
            for (String[] lineData : data) {
                printer.printRecord(lineData);
            }
        }
        logger.info("CSV文件创建成功,文件路径:{}" + filePath);
    }

    /**
     * 读取csv文件
     *
     * @param filePath 文件路径
     * @param headers  csv列头，数组的值与列数对应，而不与csv文件内的header数据对应
     * @return CSVRecord 列表
     * @throws IOException
     **/
    public static List<CSVRecord> readCSV(String filePath, String[] headers) throws IOException {
        //创建CSVFormat
        CSVFormat formator = CSVFormat.DEFAULT.withHeader(headers);
        FileReader fileReader = new FileReader(filePath);
        //创建CSVParser对象
        CSVParser parser = new CSVParser(fileReader, formator);
        List<CSVRecord> records = parser.getRecords();
        parser.close();
        fileReader.close();
        return records;
    }

    /**
     * 读取csv文件
     *
     * @param file    文件路径
     * @param headers csv列头，数组的值与列数对应，而不与csv文件内的header数据对应
     * @return CSVRecord 列表
     * @throws IOException
     **/
    public static List<CSVRecord> readCSV(File file, String[] headers) throws IOException {
        //创建CSVFormat
        CSVFormat formator = CSVFormat.DEFAULT.withHeader(headers);
        FileReader fileReader = new FileReader(file);
        //创建CSVParser对象
        CSVParser parser = new CSVParser(fileReader, formator);
        List<CSVRecord> records = parser.getRecords();
        parser.close();
        fileReader.close();
        return records;
    }

    /***
     * <T> List<T> 前面的<T>表示该方法为泛型方法，后面的<T>表示返回值类型
     * headers 为每列对应的key ,不与表头对应（即可以为clazz的属性值）
     * @param filePath
     * @param headers
     * @param clazz
     * @param <T>
     * @return
     * @throws IOException
     */
    public static <T> List<T> readCSV(String filePath, String[] headers, Class<T> clazz) throws IOException {
        List<CSVRecord> records = readCSV(filePath, headers);
        if (CollectionUtils.isEmpty(records))
            return null;
        return record2Clazz(records, clazz);
    }

    /***
     * <T> List<T> 前面的<T>表示该方法为泛型方法，后面的<T>表示返回值类型
     * headers 为每列对应的key ,不与表头对应（即可以为clazz的属性值）
     * @param file
     * @param headers
     * @param clazz
     * @param <T>
     * @return
     * @throws IOException
     */
    public static <T> List<T> readCSV(File file, String[] headers, Class<T> clazz) throws IOException {
        List<CSVRecord> records = readCSV(file, headers);
        if (CollectionUtils.isEmpty(records))
            return null;
        return record2Clazz(records, clazz);
    }

    public static <T> List<T> record2Clazz(List<CSVRecord> base, Class<T> clazz) {
        List<Object> biz = new ArrayList<>();
        base.forEach(record -> {
            biz.add(record.toMap());
        });
        return JSON.parseArray(JSON.toJSONString(biz), clazz);
    }

}